package com.yanfan.energy.config;


import com.alibaba.fastjson2.JSONArray;
import com.yanfan.common.core.mq.DeviceReport;
import com.yanfan.common.core.thingsModel.ThingsModelSimpleItem;
import com.yanfan.common.utils.DateUtils;
import com.yanfan.energy.domain.*;
import com.yanfan.energy.domain.statist.DateStatistics;
import com.yanfan.energy.domain.thingsModel.ThingsModelSimpleItem2;
import com.yanfan.energy.mapper.EnergyCopMapper;
import com.yanfan.energy.mapper.OverallEnergyMapper;
import com.yanfan.energy.service.ConfigurationCopService;
import com.yanfan.energy.service.DeviceThingsEnergyService;
import com.yanfan.energy.service.EnergyPriceSettingService;
import com.yanfan.framework.manager.AsyncManager;
import com.yanfan.iot.model.ThingsModels.ValueItem;
import com.yanfan.mq.model.ReportDataBo;
import com.yanfan.mq.service.IMqttMessageService;
import jdk.nashorn.internal.runtime.logging.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.TimerTask;
import java.util.stream.Collectors;

@Service
@Logger
public class EnergyMqttServiceImpl implements IMqttMessageService {
    private static final org.slf4j.Logger log = LoggerFactory.getLogger(EnergyMqttServiceImpl.class);
    @Autowired
    private DeviceThingsEnergyService deviceThingsEnergyService;
    @Autowired
    private OverallEnergyMapper overallEnergyMapper;
    @Value("${server.energy.enabled:false}")
    private Boolean energyEnabled;
    @Resource
    private EnergyPriceSettingService energyPriceSettingService;
    @Resource
    private ConfigurationCopService configurationCopService;
    @Resource
    private EnergyCopMapper energyCopMapper;

    @Override
    public void message(DeviceReport message, String topicName) {
        if (!energyEnabled) {
            return;
        }
        ReportDataBo report = new ReportDataBo();
        report.setSerialNumber(message.getSerialNumber());
        report.setProductId(message.getProductId());
        report.setDataList(message.getThingsModelSimpleItem());
        report.setType(1);
        report.setUserId(message.getUserId());
        report.setUserName(message.getUserName());
        report.setDeviceName(message.getDeviceName());
        report.setSources(message.getSources());
        //属性上报执行规则引擎
        report.setRuleEngine(true);
        addOverallEnergy(report);
    }

    public void addOverallEnergy(ReportDataBo bo) {
        //异步cop分析
        AsyncManager.me().execute(new TimerTask() {
            @Override
            public void run() {
                cop(bo);
            }
        });
        // 根据设备编号查询设备参数绑定能源表的数据，根据绑定的数据同步到能源表中
        List<DeviceThings> deviceThings = deviceThingsEnergyService.findDeviceThingsById(bo.getSerialNumber());

        if (!deviceThings.isEmpty()) {
            try {
                String message = JSONArray.toJSONString(bo.getDataList());
                List<ThingsModelSimpleItem2> thingsModelSimpleItems = com.alibaba.fastjson.JSON.parseArray(message, ThingsModelSimpleItem2.class);
                thingsModelSimpleItems.forEach(t -> {
                    List<DeviceThings> deviceThingsList = deviceThings
                            .stream()
                            .filter(obj -> obj.getThingsProperty().equals(t.getId()))
                            .collect(Collectors.toList());
                    deviceThingsList.forEach(de -> {
                        OverallEnergys overallEnergys = new OverallEnergys();
                        overallEnergys.setType(de.getEnergyType().intValue());
                        if (de.getEnergyType() == 7 || de.getEnergyType() == 8 || de.getEnergyType() == 9 || de.getEnergyType() == 10) {
                            overallEnergys.setTotalConsumption(t.getValue());
                            overallEnergys.setTotalzhi(t.getValue());
                            overallEnergys.setClassCode(2);
                            // 获取当前时间
                            LocalTime now = LocalTime.now();
                            Integer s = determinePeriod(now);
                            overallEnergys.setType(s);
                        } else if (de.getEnergyType() == 1 || de.getEnergyType() == 2 || de.getEnergyType() == 3) {
                            overallEnergys.setTotalDosage(t.getValue());
                            overallEnergys.setTotalzhi(t.getValue());
                            overallEnergys.setClassCode(1);
                        } else {
                            overallEnergys.setTotalDosage(t.getValue());
                            overallEnergys.setTotalzhi(t.getValue());
                            overallEnergys.setClassCode(3);
                        }
                        Long type = Long.parseLong(overallEnergys.getType().toString());
                        List<DateStatistics> dateStatistics = overallEnergyMapper.findEnergySetting();
                        List<DateStatistics> dateStatisticsList = dateStatistics
                                .stream()
                                .filter(da -> Objects.equals(da.getCount(), type))
                                .collect(Collectors.toList());
                        if (!dateStatisticsList.isEmpty()) {
                            overallEnergys.setPrice(dateStatisticsList.get(0).getNumber());
                        }
                        overallEnergys.setWorkShopId(de.getWorkshopId());
                        overallEnergys.setDeviceId(de.getDeviceId().longValue());
                        overallEnergys.setCreatedDate(DateUtils.getNowDate());
                        overallEnergys.setUseDate(DateUtils.getNowDate());
                        // 新增到能源表数据
                        if (de.getEnertype()==0) {
                            //增量计算获取最新的数据
                            Double totalzhi = overallEnergyMapper.getTotalConsumption(overallEnergys);
                            if(totalzhi != null) {
                                //获取对应能源属性的上传值，来进行数据的计算
                                Double totalConsumption1;
                                if (de.getEnergyType() == 7 || de.getEnergyType() == 8 || de.getEnergyType() == 9 || de.getEnergyType() == 10) {
                                    totalConsumption1=overallEnergys.getTotalConsumption();
                                } else if (de.getEnergyType() == 1 || de.getEnergyType() == 2 || de.getEnergyType() == 3) {
                                    totalConsumption1=overallEnergys.getTotalDosage();
                                } else {
                                    totalConsumption1=overallEnergys.getTotalDosage();
                                }
                                if(totalConsumption1-totalzhi>0){
                                    if (de.getEnergyType() == 7 || de.getEnergyType() == 8 || de.getEnergyType() == 9 || de.getEnergyType() == 10) {
                                        overallEnergys.setTotalConsumption(totalConsumption1-totalzhi);
                                    } else if (de.getEnergyType() == 1 || de.getEnergyType() == 2 || de.getEnergyType() == 3) {
                                        overallEnergys.setTotalDosage(totalConsumption1-totalzhi);
                                    } else {
                                        overallEnergys.setTotalDosage(totalConsumption1-totalzhi);
                                    }
                                }
                                else {
                                    return;
                                }
                            }
                        }
                        overallEnergyMapper.insert(overallEnergys);
                        overallEnergyMapper.insertDay(overallEnergys);
                    });
                });
            } catch (Exception e) {
                System.out.println("接收属性数据，解析数据时异常 message={}" + e.getMessage());
            }
        }
    }

    //尖峰平谷电量时间段类型
    public Integer determinePeriod(LocalTime time) {
        List<EnergyPriceSetting> allPriceElectricSetList = energyPriceSettingService.findAllPriceElectricSet();
        int hour = time.getHour();
        for (EnergyPriceSetting allPriceElectricSet : allPriceElectricSetList){
            if (hour >= allPriceElectricSet.getStartTime().getHours() && hour <= allPriceElectricSet.getEndTime().getHours()){
                return allPriceElectricSet.getType();
            }
        }
        return 0;
    }

    //cop计算（冷热量/用电量）
    public void cop(ReportDataBo bo){
        String serialNumber = bo.getSerialNumber();
        List<ConfigurationCop> configurationCops = configurationCopService.selectConfigurationCopListBySerialNumber(serialNumber);
        if (Objects.isNull(configurationCops)) {
            log.error("没有匹配的设备");
        }
        //判断是设备1还是设备2
        for (ConfigurationCop configurationCop : configurationCops) {
            //设备1
            if(configurationCop.getSerialNumber1().equals(bo.getSerialNumber())){
                String value = GetValue(bo.getDataList(), configurationCop.getIotThings1());
                if (Objects.isNull(value)) {
                    return;
                }
                DeviceThings result = DeviceThingData(configurationCop.getSerialNumber2(), configurationCop);
                if (result == null) {
                    return;
                }
                //增量计算
                if (result.getEnertype()==0) {
                    OverallEnergys overallEnergys = new OverallEnergys();
                    overallEnergys.setWorkShopId(result.getWorkshopId());
                    overallEnergys.setDeviceId(result.getDeviceId().longValue());
//                    overallEnergys.setType(result.getEnergyType().intValue());
                    Double TotalConsumption = overallEnergyMapper.getTotalConsumptionCop(overallEnergys);
                    getEnergyCop(value,TotalConsumption.toString());
                }
                //全量计算
                else {
                    String string = StrData(configurationCop.getSerialNumber2(), configurationCop.getIotThings2());
                    getEnergyCop(value,string);
                }
            }
            //设备2
            else if(configurationCop.getSerialNumber2().equals(bo.getSerialNumber())){
                String value = GetValue(bo.getDataList(), configurationCop.getIotThings2());
                if (Objects.isNull(value)) {
                    return;
                }
                DeviceThings result = DeviceThingData(bo.getSerialNumber(), configurationCop);
                if (result == null) {
                    return;
                }
                String string = StrData(configurationCop.getSerialNumber1(), configurationCop.getIotThings1());
                //增量计算
                if (result.getEnertype()==0) {
                    OverallEnergys overallEnergys = new OverallEnergys();
                    overallEnergys.setWorkShopId(result.getWorkshopId());
                    overallEnergys.setDeviceId(result.getDeviceId().longValue());
//                    overallEnergys.setType(result.getEnergyType().intValue());
                    //增量计算获取最新的数据
                    Double TotalZhi = overallEnergyMapper.getTotalConsumption(overallEnergys);
                    if(TotalZhi != null) {
                        BigDecimal a =new BigDecimal(TotalZhi);
                        BigDecimal b =new BigDecimal(value);
                        BigDecimal subtract = b.subtract(a);
                        getEnergyCop(string,subtract.toPlainString());
                    }
                    else {
                        getEnergyCop(string,value);
                    }
                }
                else {
                    getEnergyCop(string,value);
                }
            }
        }
    }

    public String GetValue(List<ThingsModelSimpleItem> dataList,String id){
        List<ThingsModelSimpleItem> collect = dataList.stream().filter(item -> item.getId().equals(id)).collect(Collectors.toList());
        if (collect.isEmpty()) {
            log.error("点位不存在");
            return null;
        }
        return collect.get(0).getValue();
    }

    public String StrData(String SerialNumber,String IotThings){
        List<ValueItem> valueItemListBySerialNumber = configurationCopService.getValueItemListBySerialNumber(SerialNumber);
        if(valueItemListBySerialNumber.isEmpty()){
            log.error("{}设备没有点位数据上报",SerialNumber);
            return "0";
        }
        ValueItem valueItem = valueItemListBySerialNumber.stream().filter(item -> item.getId().equals(IotThings)).findAny()
                .orElse(null);// 或者使用orElseThrow()抛出异常
        if (valueItem == null) {
            log.error("{}设备没有找到{}点位",SerialNumber,IotThings);
            return "0";
        }
        String TotalConsumption = valueItem.getValue();
        return TotalConsumption.isEmpty() ? "0" : TotalConsumption;
    }

    public DeviceThings DeviceThingData(String SerialNumber,ConfigurationCop configurationCop){
        //需要判断是增量还是全量的用电量
        List<DeviceThings> deviceThings = deviceThingsEnergyService.findDeviceThingsById(SerialNumber);
        if (deviceThings.isEmpty()) {
            log.error("能源配置没有绑定用电量无法知道是增量的还是全量的数据");
            return null;
        }
        DeviceThings result = deviceThings.stream()
                .filter(deviceThing -> deviceThing.getThingsProperty().equals(configurationCop.getIotThings2()))
                .findAny()
                .orElse(null); // 或者使用orElseThrow()抛出异常
        if (result == null) {
            log.error("没有用电量的配置");
            return null;
        }
        return result;
    }

    /**
     *
     * @param value 冷热量
     * @param TotalConsumption 用电量
     * @return
     */
    public void getEnergyCop(String value,String TotalConsumption){
        EnergyCopDTO energyCop = new EnergyCopDTO();
        BigDecimal a = new BigDecimal(value);
        BigDecimal b = new BigDecimal(TotalConsumption);
        if (b!= BigDecimal.ZERO) {
            BigDecimal result = a.divide(b, 2, RoundingMode.HALF_UP);
            log.info("冷热量{}/用电量{}结果为：{}",a,b,result);
            energyCop.setCreateDate(new Date());
            energyCop.setCop(result.toPlainString());
            energyCopMapper.insertCop(energyCop);
        }
    }
}
